/*
 * Copyright (c) 2022 Huawei Technologies Co.,Ltd.
 *
 * openGauss is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *
 *          http://license.coscl.org.cn/MulanPSL2
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 * -------------------------------------------------------------------------
 *
 * cm_checksum.c
 *
 *
 * IDENTIFICATION
 *    src/storage/gstor/zekernel/common/cm_checksum.c
 *
 * -------------------------------------------------------------------------
 */
#include "cm_checksum.h"

#if defined(__x86_64) && !defined(__x86_64__)
#define __x86_64__
#endif

static const uint32 g_crc32c_table_littleendian[8][256];
static const uint32 g_crc32c_table_bigendian[8][256];

#define AARCH_CRC32C_U8(crc, val)   (__crc32cb((crc), (val)))
#define AARCH_CRC32C_U16(crc, val)  (__crc32ch((crc), (val)))
#define AARCH_CRC32C_U32(crc, val)  (__crc32cw((crc), (val)))
#define AARCH_CRC32C_U64(crc, val)  (__crc32cd((crc), (val)))
#define SSE42_CRC32C_U8(crc, val)   (_mm_crc32_u8((crc), (val)))
#define SSE42_CRC32C_U32(crc, val)  (_mm_crc32_u32((crc), (val)))
#define SSE42_CRC32C_U64(crc, val)  (_mm_crc32_u64((crc), (val)))

static inline uint32 cm_crc32c_u8_lendian(uint32 crc, uint8 val)
{
    return g_crc32c_table_littleendian[0][(crc ^ val) & 0xFF] ^ (crc >> 8);
}

static inline uint32 cm_crc32c_u8_dendian(uint32 crc, uint8 val)
{
    return g_crc32c_table_bigendian[0][((crc >> 24) ^ val) & 0xFF] ^ (crc << 8);
}

#if defined(HAVE_ARM_ACLE)
bool32 cm_crc32c_aarch_available(void)
{
    uint64 check_data = 42;
    int result;

    result = (cm_crc32c_aarch(&check_data, sizeof(check_data), 0) ==
              cm_crc32c_sb8(&check_data, sizeof(check_data), 0));

    return (result > 0);
}

uint32 cm_crc32c_aarch(const void *data, uint32 len, uint32 crc)
{
    const uint8 *ptr = data;
    const uint8 *ptr_end = ptr + len;

    if (!CM_IS_ALIGN2((uintptr_t)ptr) &&
        ptr + sizeof(uint8) <= ptr_end) {
        crc = AARCH_CRC32C_U8(crc, *ptr);
        ptr += sizeof(uint8);
    }
    if (!CM_IS_ALIGN4((uintptr_t)ptr) &&
        ptr + sizeof(uint16) <= ptr_end) {
        crc = AARCH_CRC32C_U16(crc, *(uint16 *)ptr);
        ptr += sizeof(uint16);
    }
    if (!CM_IS_ALIGN8((uintptr_t)ptr) &&
        ptr + sizeof(uint32) <= ptr_end) {
        crc = AARCH_CRC32C_U32(crc, *(uint32 *)ptr);
        ptr += sizeof(uint32);
    }

    for (; ptr + sizeof(uint64) <= ptr_end; ptr += sizeof(uint64)) {
        crc = AARCH_CRC32C_U64(crc, *(uint64 *)ptr);
    }

    if (ptr + sizeof(uint32) <= ptr_end) {
        crc = AARCH_CRC32C_U32(crc, *(uint32 *)ptr);
        ptr += sizeof(uint32);
    }
    if (ptr + sizeof(uint16) <= ptr_end) {
        crc = AARCH_CRC32C_U16(crc, *(uint16 *)ptr);
        ptr += sizeof(uint16);
    }
    if (ptr < ptr_end) {
        crc = AARCH_CRC32C_U8(crc, *ptr);
    }

    return crc;
}
#endif

uint32 cm_crc32c_sse42(const void *data, uint32 len, uint32 crc)
{
#if defined(DB_HAVE_SSE4_2)
    const uint8 *ptr     = (uint8 *)data;
    const uint8 *ptr_end = ptr + len;

#ifdef __x86_64__
    for (; ptr + sizeof(uint64) <= ptr_end; ptr += sizeof(uint64)) {
        crc = (uint32)SSE42_CRC32C_U64(crc, *((const uint64 *)ptr));
    }

    if (ptr + sizeof(uint32) <= ptr_end) {
        crc = (uint32)SSE42_CRC32C_U32(crc, *((const uint32 *)ptr));
        ptr += sizeof(uint32);
    }
#else

    for (; ptr + sizeof(uint32) <= ptr_end; ptr += sizeof(uint32)) {
        crc = SSE42_CRC32C_U32(crc, *((const uint32 *)ptr));
    }
#endif

    for (; ptr < ptr_end; ptr++) {
        crc = (uint32)SSE42_CRC32C_U8(crc, *ptr);
    }
#endif

    return crc;
}

static inline uint32 cm_crc32c_sb8_align4_lendian(const uint8 **p, uint32 *length, uint32 crc)
{
    const uint8 *ptr = (*p);
    uint32       len = (*length);

    for (; len > 0 && !CM_IS_ALIGN4((uintptr_t)ptr); ptr++, len--) {
        crc = cm_crc32c_u8_lendian(crc, *ptr);
    }

    *p      = ptr;
    *length = len;
    return crc;
}

static inline uint32 cm_crc32c_sb8_align4_bendian(const uint8 **p, uint32 *length, uint32 crc)
{
    const uint8 *ptr = (*p);
    uint32       len = (*length);

    for (; len > 0 && !CM_IS_ALIGN4((uintptr_t)ptr); ptr++, len--) {
        crc = cm_crc32c_u8_dendian(crc, *ptr);
    }

    *p      = ptr;
    *length = len;
    return crc;
}

static inline uint32 cm_crc32c_sb8_align8_lendian(const uint32 **p, uint32 *length, uint32 crc)
{
    const uint32 *ptr = (*p);
    uint32       len = *length;
    uint32       first;
    uint32       second;

    for (; len >= sizeof(uint64); len -= sizeof(uint64)) {
        first = *ptr ^ crc;
        ptr++;
        second = *ptr;
        ptr++;
        crc = g_crc32c_table_littleendian[0][(uint8)(second >> 24)] ^
            g_crc32c_table_littleendian[1][(uint8)(second >> 16)] ^
            g_crc32c_table_littleendian[2][(uint8)(second >> 8)] ^
            g_crc32c_table_littleendian[3][(uint8)(second)] ^
            g_crc32c_table_littleendian[4][(uint8)(first >> 24)] ^
            g_crc32c_table_littleendian[5][(uint8)(first >> 16)] ^
            g_crc32c_table_littleendian[6][(uint8)(first >> 8)] ^
            g_crc32c_table_littleendian[7][(uint8)(first)];
    }

    *p      = ptr;
    *length = len;
    return crc;
}

static inline uint32 cm_crc32c_sb8_align8_bendian(const uint32 **p, uint32 *length, uint32 crc)
{
    const uint32 *ptr = (*p);
    uint32       len = *length;
    uint32       first;
    uint32       second;

    for (; len >= sizeof(uint64); len -= sizeof(uint64)) {
        first = *ptr ^ crc;
        ptr++;
        second = *ptr;
        ptr++;
        crc =
            g_crc32c_table_bigendian[0][(uint8)(second)] ^ g_crc32c_table_bigendian[1][(uint8)(second >> 8)] ^
            g_crc32c_table_bigendian[2][(uint8)(second >> 16)] ^ g_crc32c_table_bigendian[3][(uint8)(second >> 24)] ^
            g_crc32c_table_bigendian[4][(uint8)(first)] ^ g_crc32c_table_bigendian[5][(uint8)(first >> 8)] ^
            g_crc32c_table_bigendian[6][(uint8)(first >> 16)] ^ g_crc32c_table_bigendian[7][(uint8)(first >> 24)];
    }

    *p      = ptr;
    *length = len;
    return crc;
}

static inline uint32 cm_crc32c_sb8_remain_lendian(const uint8 *ptr, uint32 len, uint32 crc)
{
    for (; len > 0; ptr++, len--) {
        crc = cm_crc32c_u8_lendian(crc, *ptr);
    }

    return crc;
}

static inline uint32 cm_crc32c_sb8_remain_bendian(const uint8 *ptr, uint32 len, uint32 crc)
{
    for (; len > 0; ptr++, len--) {
        crc = cm_crc32c_u8_dendian(crc, *ptr);
    }

    return crc;
}

uint32 cm_crc32c_sb8(const void *data, uint32 len, uint32 crc)
{
    const uint8 *ptr     = (const uint8 *)data;

    if (!IS_BIG_ENDIAN) {
        crc = cm_crc32c_sb8_align4_lendian(&ptr, &len, crc);
        crc = cm_crc32c_sb8_align8_lendian((const uint32 **)&ptr, &len, crc);
        return cm_crc32c_sb8_remain_lendian(ptr, len, crc);
    }

    crc = cm_crc32c_sb8_align4_bendian(&ptr, &len, crc);
    crc = cm_crc32c_sb8_align8_bendian((const uint32 **)&ptr, &len, crc);
    return cm_crc32c_sb8_remain_bendian(ptr, len, crc);
}

static const uint32 g_crc32c_table_littleendian[8][256] = {
    { 000000000000, 036232701403, 034116670367, 002324171764,
    030746513437, 006574212034, 004650363750, 032462462353,
    021266254317, 017054555714, 015370424070, 023142325473,
    011520747720, 027712046323, 025436137447, 013604636044,
    002027543557, 034215242154, 036131333630, 000303432233,
    032761050160, 004553751563, 006677620207, 030445121604,
    023241717640, 015073016243, 017357167527, 021165666124,
    013507204277, 025735505674, 027411474110, 011623375513,
    004057307336, 032265406735, 030141577051, 006373276452,
    034711614701, 002523115302, 000607064466, 036435765065,
    025231153021, 013003652422, 011327723346, 027115022745,
    015577440416, 023745341015, 021461230771, 017653531372,
    006070644661, 030242145262, 032166034506, 004354735105,
    036736357256, 000504456655, 002620527131, 034412226532,
    027216410576, 011024311175, 013300260611, 025132561212,
    017550103141, 021762602542, 023446773226, 015674072625,
    010136616674, 026304117277, 024020066513, 012212767110,
    020670305243, 016442404640, 014766575124, 022554274527,
    031350442563, 007162343160, 005246232604, 033074533207,
    001416151154, 037624650557, 035500721233, 003732020630,
    012111355323, 024323454720, 026007525044, 010235224447,
    022657646714, 014465147317, 016741036473, 020573737070,
    033377101034, 005145600437, 007261771353, 031053070750,
    003431412403, 035603313000, 037527262764, 001715563367,
    014161511542, 022353210141, 020077361625, 016245460226,
    024627002175, 012415703576, 010731672212, 026503173611,
    035307745655, 003135044256, 001211135532, 037023634131,
    005441256262, 033673557661, 031557426105, 007765327506,
    016146052015, 020374753416, 022050622372, 014262123771,
    026600541422, 010432240021, 012716331745, 024524430346,
    037320206302, 001112507701, 003236476065, 035004377466,
    007466715735, 031654014336, 033570165452, 005742664051,
    020275435570, 016047334173, 014363245617, 022151544214,
    010533126147, 026701627544, 024425756220, 012617057623,
    001013661667, 037221160264, 035105011500, 003337710103,
    031755372250, 007567473653, 005643502137, 033471203534,
    022252176027, 014060677424, 016344706340, 020176007743,
    012514465410, 024726364013, 026402215777, 010630514374,
    003034322330, 035206423733, 037122552057, 001310253454,
    033772631707, 005540130304, 007664041460, 031456740063,
    024222732646, 012010033245, 010334142521, 026106643122,
    014564221271, 022756520672, 020472451116, 016640350515,
    005044566551, 033276267152, 031152316636, 007360417235,
    035702075166, 003530774565, 001614605201, 037426104602,
    026205271311, 010037570712, 012313401076, 024121300475,
    016543762726, 020771063325, 022455112441, 014667613042,
    007063025006, 031251724405, 033175655361, 005347154762,
    037725536431, 001517237032, 003633346756, 035401447355,
    030343223304, 006171522707, 004255453063, 032067352460,
    000405730733, 036637031330, 034513140454, 002721641057,
    011125077013, 027317776410, 025033607374, 013201106777,
    021663564424, 017451265027, 015775314743, 023547415340,
    032364760653, 004156061250, 006272110534, 030040611137,
    002422273264, 034610572667, 036534403103, 000706302500,
    013102534544, 025330235147, 027014344623, 011226445220,
    023644027173, 015476726570, 017752657214, 021560156617,
    034314124032, 002126625431, 000202754355, 036030055756,
    004452437405, 032660336006, 030544247762, 006776546361,
    015172370325, 023340471726, 021064500042, 017256201441,
    025634663712, 013406162311, 011722013475, 027510712076,
    036333467565, 000101366166, 002225217602, 034017516201,
    006475174152, 030647675551, 032563704235, 004751005636,
    017155633672, 021367132271, 023043043515, 015271742116,
    027613320245, 011421421646, 013705550122, 025537251521
    },
    { 000000000000, 002350514167, 004721230356, 006471724231,
    011642460734, 013512174653, 015163650462, 017233344505,
    023505141670, 021655455717, 027224371526, 025174665441,
    032347521144, 030017035023, 036466711212, 034736205375,
    007761370601, 005431664766, 003040140557, 001310454430,
    016123710135, 014273204052, 012602520263, 010552034304,
    024264231071, 026134725116, 020545001327, 022615515240,
    035426651745, 037776345622, 031307461413, 033057175574,
    017742761402, 015412275565, 013063551754, 011333045633,
    006100301336, 004250615251, 002621131060, 000571425107,
    034247620272, 036117334315, 030566410124, 032636104043,
    025405240546, 027755754421, 021324070610, 023074564777,
    010023411203, 012373105364, 014702621155, 016452335032,
    001661071537, 003531565450, 005140241661, 007210755706,
    033526550473, 031676044514, 037207760725, 035157274642,
    022364130347, 020034424220, 026445300011, 024715614176,
    037705743004, 035455257163, 033024573352, 031374067235,
    026147323730, 024217637657, 022666113466, 020536407501,
    014200602674, 016150316713, 010521432522, 012671126445,
    005442262140, 007712776027, 001363052216, 003033546371,
    030064433605, 032334127762, 034745603553, 036415317434,
    021626053131, 023576547056, 025107263267, 027257777300,
    013561572075, 011631066112, 017240742323, 015110256244,
    002323112741, 000073406626, 006402322417, 004752636570,
    020047022406, 022317536561, 024766212750, 026436706637,
    031605442332, 033555156255, 035124672064, 037274366103,
    003542163276, 001612477311, 007263353120, 005133647047,
    012300503542, 010050017425, 016421733614, 014771227773,
    027726352207, 025476646360, 023007162151, 021357476036,
    036164732533, 034234226454, 032645502665, 030515016702,
    004223213477, 006173707510, 000502023721, 002652537646,
    015461673343, 017731367224, 011340443015, 013010157172,
    037360775371, 035030261216, 033441545027, 031711051140,
    026522315445, 024672601522, 022203125713, 020153431674,
    014665634501, 016535320466, 010144404657, 012214110730,
    005027254235, 007377740352, 001706064163, 003456570004,
    030401405570, 032751111417, 034320635626, 036070321741,
    021243065244, 023113571323, 025562255112, 027632741075,
    013104544300, 011254050267, 017625774056, 015575260131,
    002746124434, 000416430553, 006067314762, 004337600605,
    020422014773, 022772500614, 024303224425, 026053730542,
    031260474047, 033130160120, 035541644311, 037611350276,
    003127155103, 001277441064, 007606365255, 005556671332,
    012765535637, 010435021750, 016044705561, 014314211406,
    027343364172, 025013670015, 023462154224, 021732440343,
    036501704646, 034651210721, 032220534510, 030170020477,
    004646225702, 006516731665, 000167015454, 002237501533,
    015004645036, 017354351151, 011725475360, 013475161207,
    000465036375, 002735522212, 004344206023, 006014712144,
    011227456441, 013177142526, 015506666717, 017656372670,
    023160177505, 021230463462, 027641347653, 025511653734,
    032722517231, 030472003356, 036003727167, 034353233000,
    007304346574, 005054652413, 003425176622, 001775462745,
    016546726240, 014616232327, 012267516116, 010137002071,
    024601207304, 026551713263, 020120037052, 022270523135,
    035043667430, 037313373557, 031762457766, 033432143601,
    017327757777, 015077243610, 013406567421, 011756073546,
    006565337043, 004635623124, 002244107315, 000114413272,
    034622616107, 036572302060, 030103426251, 032253132336,
    025060276633, 027330762754, 021741046565, 023411552402,
    010446427176, 012716133011, 014367617220, 016037303347,
    001204047642, 003154553725, 005525277514, 007675763473,
    033143566706, 031213072661, 037662756450, 035532242537,
    022701106032, 020451412155, 026020336364, 024370622203
    },
    { 000000000000, 024520311176, 011733651015, 035213540163,
    023667522032, 007347633144, 032154373027, 016474062151,
    007024237305, 023504126273, 016717466310, 032237777266,
    024643715337, 000363404241, 035170144322, 011450255254,
    016050476612, 032570767764, 007763227607, 023243136771,
    035637154620, 011317245756, 024104705635, 000424414743,
    011074641517, 035554550461, 000747010502, 024267301474,
    032613363525, 016333072453, 023120532530, 007400623446,
    034121175424, 010401264552, 025612724431, 001332435547,
    017746457416, 033266746560, 006075206403, 022555117575,
    033105342721, 017425053657, 022636513734, 006316602642,
    010762660713, 034242571665, 001051031706, 025571320670,
    022171503236, 006451612340, 033642352223, 017362043355,
    001716021204, 025236330372, 010025670211, 034505561367,
    025155734133, 001475425045, 034666165126, 010346274050,
    006732216101, 022212107077, 017001447114, 033521756062,
    030731300331, 014211011247, 021002551324, 005522640252,
    013156622303, 037476533275, 002665073316, 026345362260,
    037715137034, 013235226142, 026026766021, 002506477157,
    014172415006, 030452704170, 005641244013, 021361155165,
    026761776523, 002241467455, 037052127536, 013572236440,
    005106254511, 021426145467, 014635405504, 030315714472,
    021745541626, 005265650750, 030076310633, 014556001745,
    002122063614, 026402372762, 013611632601, 037331523777,
    004610275715, 020330164663, 015123424700, 031403735676,
    027077757727, 003557446651, 036744106732, 012264217644,
    003634042410, 027314353566, 012107613405, 036427502573,
    020053560422, 004573671554, 031760331437, 015240020541,
    012640603107, 036360512071, 003173052112, 027453343064,
    031027321135, 015507030043, 020714570120, 004234661056,
    015664434202, 031344725374, 004157265217, 020477174361,
    036003116230, 012523207346, 027730747225, 003210456353,
    021311673503, 005631562475, 030422022516, 014102333460,
    002576351531, 026056040447, 013245500524, 037765611452,
    026335444606, 002615755770, 037406215613, 013126104765,
    005552166634, 021072277742, 014261737621, 030741426757,
    037341205311, 013661114267, 026472454304, 002152745272,
    014526727323, 030006436255, 005215176336, 021735267240,
    030365032014, 014645323162, 021456663001, 005176572177,
    013502510026, 037022601150, 002231341033, 026711050145,
    015230706127, 031710417051, 004503157132, 020023246044,
    036457224115, 012177135063, 027364475100, 003644764076,
    012214531222, 036734620354, 003527360237, 027007071341,
    031473013210, 015153302366, 020340642205, 004660553373,
    003260370735, 027740061643, 012553521720, 036073630656,
    020407652707, 004127543671, 031334003712, 015614312664,
    004244147430, 020764256546, 015577716425, 031057407553,
    027423465402, 003103774574, 036310234417, 012630125561,
    011420573632, 035100662744, 000313322627, 024633033751,
    032247051600, 016767340776, 023574600615, 007054511763,
    016404744537, 032124455441, 007337115522, 023617204454,
    035263266505, 011743177473, 024550437510, 000070726466,
    007470105020, 023150214156, 016343754035, 032663445143,
    024217427012, 000737736164, 035524276007, 011004167171,
    000454332325, 024174023253, 011367563330, 035647672246,
    023233610317, 007713501261, 032500041302, 016020350274,
    025501406216, 001021717360, 034232257203, 010712146375,
    006366124224, 022646235352, 017455775231, 033175464347,
    022525631113, 006005520065, 033216060106, 017736371070,
    001342313121, 025662002057, 010471542134, 034151653042,
    033551070404, 017071361572, 022262621411, 006742530567,
    010336552436, 034616643540, 001405303423, 025125012555,
    034575247701, 010055156677, 025246416714, 001766707662,
    017312765733, 033632474645, 006421134726, 022101225650
    },
    { 000000000000, 033521325270, 027731621601, 014210504471,
    017310430763, 024631715513, 030421211162, 003100134312,
    036621061746, 005300344536, 011110640147, 022431565337,
    021531451025, 012010774255, 006200270624, 035721155454,
    035131130475, 006410215605, 012600711274, 021321434004,
    022221500316, 011700625166, 005510321517, 036031004767,
    003710151333, 030231274143, 024021770532, 017500455742,
    014400561450, 027121644620, 033331340251, 000610065021,
    032711212213, 001230137063, 015020433412, 026501716662,
    025401622570, 016120507700, 002330003371, 031611326101,
    004130273555, 037411156725, 023601452354, 010320777124,
    013220643236, 020701566046, 034511062437, 007030347647,
    007620322666, 034301007416, 020111503067, 013430626217,
    010530712105, 023011437375, 037201133704, 004720216574,
    031001343120, 002520066350, 016730562721, 025211647551,
    026311773643, 015630456433, 001420152042, 032101277232,
    025351457747, 016670772537, 002460276146, 031141153336,
    032041067024, 001560342254, 015770646625, 026251563455,
    013570436001, 020051713271, 034241217600, 007760132470,
    004660006762, 037341323512, 023151627163, 010470502313,
    010260567332, 023741642142, 037551346533, 004070063743,
    007170157451, 034451272621, 020641776250, 013360453020,
    026441506474, 015160623604, 001370327275, 032651002005,
    031751136317, 002270213167, 016060717516, 025541432766,
    017440645554, 024161560724, 030371064355, 003650341125,
    000750275237, 033271150047, 027061454436, 014540771646,
    021261624212, 012740501062, 006550005413, 035071320663,
    036171214571, 005450131701, 011640435370, 022361710100,
    022571775121, 011050450351, 005240154720, 036761271550,
    035661345642, 006340060432, 012150564043, 021471641233,
    014350714667, 027671431417, 033461135066, 000140210216,
    003040324104, 030561001374, 024771505705, 017250620575,
    012250144477, 021771261607, 035561765276, 006040440006,
    005140574314, 036461651164, 022671355515, 011350070765,
    024471125331, 017150200141, 003340704530, 030661421740,
    033761515452, 000240630622, 014050334253, 027571011023,
    027361074002, 014640351272, 000450655603, 033171570473,
    030071444761, 003550761511, 017740265160, 024261140310,
    011540015744, 022061330534, 036271634145, 005750511335,
    006650425027, 035371700257, 021161204626, 012440121456,
    020541356664, 013060073414, 007270577065, 034751652215,
    037651766107, 004370443377, 010160147706, 023441262576,
    016360337122, 025641012352, 031451516723, 002170633553,
    001070707641, 032551422431, 026741126040, 015260203230,
    015470266211, 026151143061, 032341447410, 001660762660,
    002760656572, 031241573702, 025051077373, 016570352103,
    023251207557, 010770122727, 004560426356, 037041703126,
    034141637234, 007460512044, 013670016435, 020351333645,
    037101513330, 004420636140, 010630332531, 023311017741,
    020211123453, 013730206623, 007520702252, 034001427022,
    001720572476, 032201657606, 026011353277, 015530076007,
    016430142315, 025111267165, 031301763514, 002620446764,
    002030423745, 031511706535, 025701202144, 016220127334,
    015320013026, 026601336256, 032411632627, 001130517457,
    034611442003, 007330767273, 013120263602, 020401146472,
    023501072760, 010020357510, 004230653161, 037711576311,
    005610701123, 036331424353, 022121120722, 011400205552,
    012500331640, 021021014430, 035231510041, 006710635231,
    033031760665, 000510445415, 014700141064, 027221264214,
    024321350106, 017600075376, 003410571707, 030131654577,
    030721631556, 003200514726, 017010010357, 024531335127,
    027431201235, 014110124045, 000300420434, 033621705644,
    006100650210, 035421575060, 021631071411, 012310354661,
    011210260573, 022731145703, 036521441372, 005000764102
    },
    { 000000000000, 007004267654, 016010557530, 011014730364,
    034021337260, 033025150434, 022031660750, 025035407104,
    030531605621, 037535462075, 026521352311, 021525135545,
    004510532441, 003514755215, 012500065171, 015504202725,
    021710460723, 026714607177, 037700137213, 030704350447,
    015731757543, 012735530317, 003721200073, 004725067627,
    011221265102, 016225002756, 007231732432, 000235555266,
    025200152362, 022204335536, 033210405652, 034214662006,
    003352132527, 004356355373, 015342465017, 012346602643,
    037373205747, 030377062113, 021363752277, 026367535423,
    033663737306, 034667550552, 025673260636, 022677007062,
    007642400166, 000646667732, 011652157456, 016656330202,
    022442552204, 025446735450, 034452005734, 033456262160,
    016463665064, 011467402630, 000473332554, 007477155300,
    012173357425, 015177130271, 004163600115, 003167467741,
    026152060645, 021156207011, 030142537375, 037146750521,
    006724265256, 001720002402, 010734732766, 017730555132,
    032705152036, 035701335662, 024715405506, 023711662352,
    036215460477, 031211607223, 020205137147, 027201350713,
    002234757617, 005230530043, 014224200327, 013220067573,
    027034605575, 020030462321, 031024352045, 036020135611,
    013015532715, 014011755141, 005005065225, 002001202471,
    017505000354, 010501267500, 001515557664, 006511730030,
    023524337134, 024520150760, 035534660404, 032530407250,
    005476357771, 002472130125, 013466600241, 014462467415,
    031457060511, 036453207345, 027447537021, 020443750675,
    035147552150, 032143735704, 023157005460, 024153262234,
    001166665330, 006162402564, 017176332600, 010172155054,
    024366737052, 023362550606, 032376260562, 035372007336,
    010347400232, 017343667466, 006357157702, 001353330156,
    014657132673, 013653355027, 002647465343, 005643602517,
    020676205413, 027672062247, 036666752123, 031662535777,
    015650552534, 012654735360, 003640005004, 004644262650,
    021671665754, 026675402100, 037661332264, 030665155430,
    025361357315, 022365130541, 033371600625, 034375467071,
    011340060175, 016344207721, 007350537445, 000354750211,
    034140132217, 033144355443, 022150465727, 025154602173,
    000161205077, 007165062623, 016171752547, 011175535313,
    004471737436, 003475550262, 012461260106, 015465007752,
    030450400656, 037454667002, 026440157366, 021444330532,
    016502460013, 011506607647, 000512137523, 007516350377,
    022523757273, 025527530427, 034533200743, 033537067117,
    026033265632, 021037002066, 030023732302, 037027555556,
    012012152452, 015016335206, 004002405162, 003006662736,
    037212000730, 030216267164, 021202557200, 026206730454,
    003233337550, 004237150304, 015223660060, 012227407634,
    007723605111, 000727462745, 011733352421, 016737135275,
    033702532371, 034706755525, 025712065641, 022716202015,
    013174737762, 014170550136, 005164260252, 002160007406,
    027155400502, 020151667356, 031145157032, 036141330666,
    023445132143, 024441355717, 035455465473, 032451602227,
    017464205323, 010460062577, 001474752613, 006470535047,
    032664357041, 035660130615, 024674600571, 023670467325,
    006645060221, 001641207475, 010655537711, 017651750145,
    002355552660, 005351735034, 014345005350, 013341262504,
    036374665400, 031370402254, 020364332130, 027360155764,
    010226605245, 017222462411, 006236352775, 001232135121,
    024207532025, 023203755671, 032217065515, 035213202341,
    020717000464, 027713267230, 036707557154, 031703730700,
    014736337604, 013732150050, 002726660334, 005722407560,
    031536265566, 036532002332, 027526732056, 020522555602,
    005517152706, 002513335152, 013507405236, 014503662462,
    001007460347, 006003607513, 017017137677, 010013350023,
    035026757127, 032022530773, 023036200417, 024032067243
    },
    { 000000000000, 035714065431, 033343120303, 006457145732,
    026275233567, 013561256156, 015136313664, 020622376255,
    014001414037, 021715471406, 027342534334, 012456551705,
    032274627550, 007560642161, 001137707653, 034623762262,
    030003030076, 005717055447, 003340110375, 036454175744,
    016276203511, 023562266120, 025135323612, 010621346223,
    024002424041, 011716441470, 017341504342, 022455561773,
    002277617526, 037563672117, 031134737625, 004620752214,
    020575013215, 015261076624, 013636133116, 026122156527,
    006700220772, 033014245343, 035443300471, 000357365040,
    034574407222, 001260462613, 007637527121, 032123542510,
    012701634745, 027015651374, 021442714446, 014356771077,
    010576023263, 025262046652, 023635103160, 016121166551,
    036703210704, 003017275335, 005440330407, 030354355036,
    004577437254, 031263452665, 037634517157, 002120572566,
    022702604733, 017016661302, 011441724430, 024355741001,
    001601055753, 034115030362, 032542175450, 007256110061,
    027474266234, 012360203605, 014737346137, 021023323506,
    015600441764, 020114424355, 026543561467, 013257504056,
    033475672203, 006361617632, 000736752100, 035022737531,
    031602065725, 004116000314, 002541145426, 037255120017,
    017477256242, 022363233673, 024734376141, 011020313570,
    025603471712, 010117414323, 016540551411, 023254534020,
    003476642275, 036362627644, 030735762176, 005021707547,
    021374046546, 014460023177, 012037166645, 027723103274,
    007101275021, 032615210410, 034242355322, 001556330713,
    035375452571, 000461437140, 006036572672, 033722517243,
    013100661016, 026614604427, 020243741315, 015557724724,
    011377076530, 024463013101, 022034156633, 017720133202,
    037102245057, 002616220466, 004241365354, 031555300765,
    005376462507, 030462407136, 036035542604, 003721527235,
    023103651060, 016617634451, 010240771363, 025554714752,
    003402133726, 036316156317, 030741013425, 005055076014,
    025677300241, 010163365670, 016534220142, 023220245573,
    017403527711, 022317542320, 024740407412, 011054462023,
    031676714276, 004162771647, 002535634175, 037221651544,
    033401103750, 006315166361, 000742023453, 035056046062,
    015674330237, 020160355606, 026537210134, 013223275505,
    027400517767, 012314572356, 014743437464, 021057452055,
    001675724200, 034161741631, 032536604103, 007222661532,
    023177120533, 016663145102, 010234000630, 025520065201,
    005302313054, 030416376465, 036041233357, 003755256766,
    037176534504, 002662551135, 004235414607, 031521471236,
    011303707063, 024417762452, 022040627360, 017754642751,
    013174110545, 026660175174, 020237030646, 015523055277,
    035301323022, 000415346413, 006042203321, 033756266710,
    007175504572, 032661561143, 034236424671, 001522441240,
    021300737015, 014414752424, 012043617316, 027757672727,
    002203166075, 037517103444, 031140046376, 004654023747,
    024076355512, 011762330123, 017335275611, 022421210220,
    016202572042, 023516517473, 025141452341, 010655437770,
    030077741525, 005763724114, 003334661626, 036420604217,
    032200156003, 007514133432, 001143076300, 034657013731,
    014075365564, 021761300155, 027336245667, 012422220256,
    026201542034, 013515527405, 015142462337, 020656407706,
    000074771553, 035760714162, 033337651650, 006423634261,
    022776175260, 017062110651, 011435055163, 024321030552,
    004503346707, 031217323336, 037640266404, 002154203035,
    036777561257, 003063504666, 005434441154, 030320424565,
    010502752730, 025216737301, 023641672433, 016155617002,
    012775145216, 027061120627, 021436065115, 014322000524,
    034500376771, 001214313340, 007643256472, 032157233043,
    006774551221, 033060534610, 035437471122, 000323414513,
    020501762746, 015215707377, 013642642445, 026156627074
    },
    { 000000000000, 015000626310, 032001454620, 027001272530,
    024570142721, 031570764431, 016571516101, 003571330211,
    011613376523, 004613550633, 023612722303, 036612104013,
    035363234202, 020363412112, 007362660422, 012362046732,
    023426775246, 036426153156, 011427321466, 004427507776,
    007156637567, 012156011677, 035157263347, 020157445057,
    032235403765, 027235225475, 000234057145, 015234671255,
    016745541044, 003745367354, 024744115664, 031744733574,
    007526701675, 012526127565, 035527355055, 020527573345,
    023056643154, 036056065244, 011057217774, 004057431464,
    016335477356, 003335251046, 024334023576, 031334605666,
    032645535477, 027645313767, 000644161257, 015644747147,
    024100074433, 031100652723, 016101420213, 003101206103,
    000470136312, 015470710002, 032471562532, 027471344622,
    035713302110, 020713524200, 007712756730, 012712170420,
    011263240631, 004263466521, 023262614011, 036262032301,
    017255603572, 002255025662, 025254257352, 030254471042,
    033725741253, 026725167143, 001724315473, 014724533763,
    006446575051, 013446353341, 034447121671, 021447707561,
    022136437770, 037136211460, 010137063150, 005137645240,
    034673176734, 021673750424, 006672522114, 013672304204,
    010303034015, 005303612305, 022302460635, 037302246525,
    025060200217, 030060426107, 017061654437, 002061072727,
    001510342536, 014510564626, 033511716316, 026511130006,
    010773102307, 005773724017, 022772556527, 037772370637,
    034203040426, 021203666736, 006202414206, 013202232116,
    001160274624, 014160452534, 033161620004, 026161006314,
    025410336105, 030410510215, 017411762725, 002411144435,
    033355677141, 026355051251, 001354223761, 014354405471,
    017625735660, 002625113570, 025624361040, 030624547350,
    022546501462, 037546327772, 010547155242, 005547773152,
    006036443343, 013036265053, 034037017563, 021037631673,
    036533407364, 023533221074, 004532053544, 011532675654,
    012043545445, 007043363755, 020042111265, 035042737175,
    027320771647, 032320157557, 015321325067, 000321503377,
    003650633166, 016650015276, 031651267746, 024651441456,
    015115372122, 000115554232, 027114726702, 032114100412,
    031465230603, 024465416513, 003464664023, 016464042333,
    004706004401, 011706622711, 036707450221, 023707276131,
    020276146320, 035276760030, 012277512500, 007277334610,
    031015306511, 024015520601, 003014752331, 016014174021,
    015565244230, 000565462120, 027564610410, 032564036700,
    020606070032, 035606656322, 012607424612, 007607202502,
    004376132713, 011376714403, 036377566133, 023377340223,
    012433473757, 007433255447, 020432027177, 035432601267,
    036143531076, 023143317366, 004142165656, 011142743546,
    003220705274, 016220123164, 031221351454, 024221577744,
    027750647555, 032750061645, 015751213375, 000751435065,
    021766204616, 034766422506, 013767650036, 006767076326,
    005216346137, 010216560227, 037217712717, 022217134407,
    030175172335, 025175754025, 002174526515, 017174300605,
    014405030414, 001405616704, 026404464234, 033404242124,
    002340571450, 017340357740, 030341125270, 025341703160,
    026630433371, 033630215061, 014631067551, 001631641641,
    013553607173, 006553021263, 021552253753, 034552475443,
    037023745652, 022023163542, 005022311072, 010022537362,
    026240505063, 033240323373, 014241151643, 001241777553,
    002730447742, 017730261452, 030731013162, 025731635272,
    037453673540, 022453055650, 005452227360, 010452401070,
    013123731261, 006123117171, 021122365441, 034122543751,
    005666270225, 010666456135, 037667624405, 022667002715,
    021316332504, 034316514614, 013317766324, 006317140034,
    014075106706, 001075720416, 026074552126, 033074374236,
    030505044027, 025505662337, 002504410607, 017504236517
    },
    { 000000000000, 011117076447, 022236175116, 033321103551,
    004107301155, 015010377512, 026331274043, 037226202404,
    010216602332, 001301674775, 032020777224, 023137701663,
    014311503267, 005206575620, 036127476371, 027030400736,
    020435404664, 031522472223, 002603571772, 013714507335,
    024532705731, 035425773376, 006704670627, 017613606260,
    030623206556, 021734270111, 012415373440, 003502305007,
    034724107403, 025633171044, 016512072515, 007405004152,
    001500062631, 010417014276, 023736117727, 032621161360,
    005407363764, 014510315323, 027631216672, 036726260235,
    011716660503, 000601616144, 033520715415, 022437763052,
    015611561456, 004706517011, 037427414540, 026530462107,
    021135466055, 030022410412, 003303513143, 012214565504,
    025032767100, 034125711547, 007204612016, 016313664451,
    031323264367, 020234212720, 013115311271, 002002367636,
    035224165232, 024333113675, 017012010324, 006105066763,
    003200145462, 012317133025, 021036030574, 030121046133,
    007307244537, 016210232170, 025131331421, 034026347066,
    013016747750, 002101731317, 031220632646, 020337644201,
    017111446605, 006006430242, 035327533713, 024230545354,
    023635541206, 032722537641, 001403434310, 010514442757,
    027732640353, 036625636714, 005504735245, 014413743602,
    033423343134, 022534335573, 011615236022, 000702240465,
    037524042061, 026433034426, 015712137177, 004605141530,
    002700127253, 013617151614, 020536052345, 031421024702,
    006607226306, 017710250741, 024431353210, 035526325657,
    012516725161, 003401753526, 030720650077, 021637626430,
    016411424034, 007506452473, 034627551122, 025730527565,
    022335523437, 033222555070, 000103456521, 011014420166,
    026232622562, 037325654125, 004004757474, 015113721033,
    032123321705, 023034357342, 010315254613, 001202222254,
    036024020650, 027133056217, 014212155746, 005305123301,
    006400313144, 017517365503, 024636266052, 035721210415,
    002507012011, 013410064456, 020731167107, 031626111540,
    016616511276, 007701567631, 034420464360, 025537412727,
    012711610323, 003606666764, 030527765235, 021430713672,
    026035717720, 037122761367, 004203662636, 015314614271,
    022132416675, 033025460232, 000304563763, 011213515324,
    036223115412, 027334163055, 014015060504, 005102016143,
    032324214547, 023233262100, 010112361451, 001005317016,
    007100371775, 016017307332, 025336204663, 034221272224,
    003007070620, 012110006267, 021231105736, 030326173371,
    017316573447, 006201505000, 035120406551, 024037470116,
    013211672512, 002306604155, 031027707404, 020130771043,
    027535775111, 036422703556, 005703600007, 014614676440,
    023432474044, 032525402403, 001604501152, 010713577515,
    037723177223, 026634101664, 015515002335, 004402074772,
    033624276376, 022733200731, 011412303260, 000505375627,
    005600256526, 014717220161, 027436323430, 036521355077,
    001707157473, 010610121034, 023531022565, 032426054122,
    015416454614, 004501422253, 037620521702, 026737557345,
    011511755741, 000406723306, 033727620657, 022630656210,
    025235652342, 034322624705, 007003727254, 016114751613,
    021332553217, 030225525650, 003104426301, 012013450746,
    035023050070, 024134026437, 017215125166, 006302153521,
    031124351125, 020033327562, 013312224033, 002205252474,
    004300234317, 015217242750, 026136341201, 037021337646,
    000207135242, 011310143605, 022031040354, 033126036713,
    014116436025, 005001440462, 036320543133, 027237535574,
    010011737170, 001106741537, 032227642066, 023330634421,
    024735630573, 035622646134, 006503745465, 017414733022,
    020632531426, 031725547061, 002404444530, 013513432177,
    034523032641, 025434044206, 016715147757, 007602131310,
    030424333714, 021533345353, 012612246602, 003705230245
    }
};

static const uint32 g_crc32c_table_bigendian[8][256] = {
    { 000000000000, 000340665762, 036734035741, 036474650023,
    003745715307, 003405170465, 035071720446, 035331145324,
    031726154612, 031466731170, 007012161153, 007352704631,
    032063641515, 032323024277, 004757674254, 004417011536,
    015761657020, 015421032742, 023055662761, 023315007003,
    016024142327, 016364727445, 020710177466, 020450712304,
    024047703632, 024307166150, 012773736173, 012433153611,
    027702016535, 027442673257, 011036023274, 011376646516,
    033643536440, 033503353322, 005177503301, 005237366463,
    030106223747, 030246446025, 006632216006, 006572473764,
    002165462252, 002225207530, 034651457513, 034511232271,
    001620377155, 001560512637, 037114342614, 037254527176,
    026122361460, 026262504302, 010616354321, 010556531443,
    025667474767, 025527211005, 013153441026, 013213224744,
    017604235272, 017544450510, 021130200533, 021270465251,
    014141520175, 014201345617, 022675515634, 022535370156,
    027407275501, 027747410263, 011333240240, 011073425522,
    024342560606, 024002305164, 012476555147, 012736330625,
    016321321313, 016061544471, 020415314452, 020755571330,
    015464434014, 015724251776, 023350401755, 023010264037,
    032366422521, 032026247243, 004452417260, 004712272502,
    031423337626, 031763552144, 007317302167, 007057567605,
    003440576333, 003700313451, 035374543472, 035034326310,
    000305263034, 000045406756, 036431256775, 036771433017,
    014244743141, 014104126623, 022570776600, 022630113162,
    017501056246, 017641633524, 021235063507, 021175606265,
    025562617753, 025622072031, 013256622012, 013116047770,
    026227102454, 026167767336, 010513137315, 010653752477,
    001525114161, 001665771603, 037211121620, 037151744142,
    002260601266, 002120064504, 034554634527, 034614051245,
    030203040773, 030143625011, 006537075032, 006677610750,
    033546755474, 033606130316, 005272760335, 005132105457,
    017016773202, 017356116560, 021722746543, 021462123221,
    014753066105, 014413603667, 022067053644, 022327636126,
    026730627410, 026470042372, 010004612351, 010344077433,
    025075132717, 025335757075, 013741107056, 013401762734,
    002777124222, 002437741540, 034043111563, 034303774201,
    001032631125, 001372054647, 037706604664, 037446061106,
    033051070430, 033311615352, 005765045371, 005425620413,
    030714765737, 030454100055, 006020750076, 006360135714,
    024655245642, 024515420120, 012161270103, 012221415661,
    027110550545, 027250335227, 011624565204, 011564300566,
    015173311050, 015233574732, 023647324711, 023507541073,
    016636404357, 016576261435, 020102431416, 020242254374,
    031134412662, 031274277100, 007600427123, 007540242641,
    032671307565, 032531562207, 004145332224, 004205557546,
    000612546070, 000552323712, 036126573731, 036266316053,
    003157253377, 003217436415, 035663266436, 035523403354,
    030411506703, 030751363061, 006325533042, 006065356720,
    033354213404, 033014476366, 005460226345, 005720443427,
    001337452111, 001077237673, 037403467650, 037743202132,
    002472347216, 002732522574, 034346372557, 034006517235,
    025370351723, 025030534041, 013444364062, 013704501700,
    026435444424, 026775221346, 010301471365, 010041214407,
    014456205131, 014716460653, 022362230670, 022022455112,
    017313510236, 017053375554, 021427525577, 021767340215,
    003252030343, 003112655421, 035566005402, 035626660360,
    000517725044, 000657140726, 036223710705, 036163175067,
    032574164551, 032634701233, 004240151210, 004100734572,
    031231671656, 031171014134, 007505644117, 007645021675,
    016533667363, 016673002401, 020207652422, 020147037340,
    015276172064, 015136717706, 023542147725, 023602722047,
    027215733571, 027155156213, 011521706230, 011661163552,
    024550026676, 024610643114, 012264013137, 012124676655
    },
    { 000000000000, 016746121023, 035614042447, 023152163464,
    033430305116, 025376224135, 006224347551, 010562266572,
    027060612235, 031726733216, 012674650672, 004132771651,
    014450517323, 002316436300, 021244555764, 037502474747,
    020174342477, 036632263454, 015760300030, 003026221013,
    013544047561, 005202166542, 026350005126, 030416124105,
    007114550642, 011652471661, 032700512205, 024046433226,
    034524655754, 022262774777, 001330617313, 017476736330,
    000270705577, 016536624554, 035464747130, 023322666113,
    033640400461, 025106521442, 006054442026, 010712563005,
    027210117742, 031556036761, 012404155305, 004342074326,
    014620212654, 002166333677, 021034250213, 037772371230,
    020304447100, 036442566123, 015510405547, 003256524564,
    013734742016, 005072663035, 026120700451, 030666621472,
    007364255335, 011422374316, 032570217772, 024236336751,
    034754150223, 022012071200, 001140112664, 017606033647,
    000461413777, 016327532754, 035275451330, 023533570313,
    033051716661, 025717637642, 006645754226, 010103675205,
    027401201542, 031347320561, 012215243105, 004553362126,
    014031104454, 002777025477, 021625146013, 037163067030,
    020515751300, 036253670323, 015301713747, 003447632764,
    013125454216, 005663575235, 026731416651, 030077537672,
    007575143135, 011233062116, 032361101572, 024427020551,
    034145246023, 022603367000, 001751204464, 017017325447,
    000611316200, 016157237223, 035005354647, 023743275664,
    033221013316, 025567132335, 006435051751, 010373170772,
    027671504035, 031137425016, 012065546472, 004723467451,
    014241601123, 002507720100, 021455643564, 037313762547,
    020765054677, 036023175654, 015171016230, 003637137213,
    013355351761, 005413270742, 026541313326, 030207232305,
    007705646442, 011043767461, 032111604005, 024657725026,
    034335543554, 022473462577, 001521501113, 017267420130,
    037176541773, 021630460750, 002762503334, 014024422317,
    004546644665, 012200765646, 031352606222, 027414727201,
    010116353546, 006650272565, 025702311101, 033044230122,
    023526056450, 035260177473, 016332014017, 000474135034,
    017002603304, 001744722327, 022616641743, 034150760760,
    024432506212, 032374427231, 011226544655, 007560465676,
    030062011131, 026724130112, 005676053576, 013130172555,
    003452314027, 015314235004, 036246356460, 020500277443,
    037306244204, 021440365227, 002512206643, 014254327660,
    004736141312, 012070060331, 031122103755, 027664022776,
    010366456031, 006420577012, 025572414476, 033234535455,
    023756753127, 035010672104, 016142711560, 000604630543,
    017272106673, 001534027650, 022466144234, 034320065217,
    024642203765, 032104322746, 011056241322, 007710360301,
    030212714446, 026554635465, 005406756001, 013340677022,
    003622411550, 015164530573, 036036453117, 020770572134,
    037517152004, 021251073027, 002303110443, 014445031460,
    004127257112, 012661376131, 031733215555, 027075334576,
    010577740231, 006231661212, 025363702676, 033425623655,
    023147445327, 035601564304, 016753407760, 000015526743,
    017463210473, 001325331450, 022277252034, 034531373017,
    024053115565, 032715034546, 011647157122, 007101076101,
    030403402646, 026345523665, 005217440201, 013551561222,
    003033707750, 015775626773, 036627745317, 020161664334,
    037767657573, 021021776550, 002173615134, 014635734117,
    004357552465, 012411473446, 031543510022, 027205431001,
    010707045746, 006041164765, 025113007301, 033655126322,
    023337340650, 035471261673, 016523302217, 000265223234,
    017613515104, 001155434127, 022007557543, 034741476560,
    024223610012, 032565731031, 011437652455, 007371773476,
    030673307331, 026135226312, 005067345776, 013721264755,
    003243002227, 015505123204, 036457040660, 020311161643
    },
    { 000000000000, 017644440645, 001524467517, 016360027352,
    003251157236, 014415517473, 002775530721, 015131170164,
    030517450470, 027353010235, 031033037167, 026677477722,
    033746507646, 024102147003, 032262160351, 025426520514,
    021237321160, 036473761725, 020713746477, 037157306232,
    022066276356, 035622636513, 023542611641, 034306251004,
    011720771510, 006164331355, 010204316007, 007440756642,
    012571626726, 005335266163, 013055241231, 004611601474,
    002476642341, 015232202504, 003152225656, 014716665013,
    001627715177, 016063355732, 000303372460, 017547732225,
    032161212731, 025725652174, 033445675226, 024201235463,
    031330345507, 026574705342, 030614722010, 027050362655,
    023641563221, 034005123464, 022365104736, 035521544173,
    020410434017, 037254074652, 021134053500, 036770413345,
    013356133651, 004512573014, 012672554346, 005036114503,
    010107064467, 007743424222, 011423403170, 006267043735,
    033140062707, 024704422142, 032464405210, 025220045455,
    030311135531, 027555575374, 031635552026, 026071112663,
    003457432377, 014213072532, 002173055660, 015737415025,
    000606565141, 017042125704, 001322102456, 016566542213,
    012377343667, 005533703022, 013653724370, 004017364535,
    011126214451, 006762654214, 010402673146, 007246233703,
    022660713217, 035024353452, 023344374700, 034500734145,
    021431644021, 036275204664, 020115223536, 037751663373,
    031536620446, 026372260203, 030012247151, 027656607714,
    032767777670, 025123337035, 033243310367, 024407750522,
    001021270036, 016665630673, 000505617521, 017341257364,
    002270327200, 015434767445, 003754740717, 014110300152,
    010701501526, 007145141363, 011225166031, 006461526674,
    013550456710, 004314016155, 012074031207, 005630471442,
    020216151156, 037452511713, 021732536441, 036176176204,
    023047006360, 034603446525, 022563461677, 035327021032,
    010335623613, 007571263056, 011611244304, 006055604541,
    013164774425, 004720334260, 012440313132, 005204753777,
    020622273263, 037066633426, 021306614774, 036542254131,
    023473324055, 034237764610, 022157743542, 035713303307,
    031102502773, 026746142136, 030426165264, 027262525421,
    032353455545, 025517015300, 033677032052, 024033472617,
    001415152303, 016251512546, 000131535614, 017775175051,
    002644005135, 015000445770, 003360462422, 014524022267,
    012743061552, 005107421317, 013267406045, 004423046600,
    011512136764, 006356576121, 010036551273, 007672111436,
    022254431122, 035410071767, 023770056435, 034134416270,
    021005566314, 036641126551, 020521101603, 037365541046,
    033574340432, 024330700277, 032050727125, 025614367760,
    030725217604, 027161657041, 031201670313, 026445230556,
    003063710042, 014627350607, 002547377555, 015303737310,
    000232647274, 017476207431, 001716220763, 016152660126,
    023275641114, 034431201751, 022751226403, 035115666246,
    020024716322, 037660356567, 021500371635, 036344731070,
    013762211564, 004126651321, 012246676073, 005402236636,
    010533346752, 007377706117, 011017721245, 006653361400,
    002042560074, 015606120631, 003566107563, 014322547326,
    001213437242, 016457077407, 000737050755, 017173410110,
    032555130404, 025311570241, 033071557113, 024635117756,
    031704067632, 026140427077, 030220400325, 027464040560,
    021603003255, 036047443410, 020327464742, 037563024107,
    022452154063, 035216514626, 023176533574, 034732173331,
    011314453625, 006550013060, 010630034332, 007074474577,
    012145504413, 005701144256, 013461163104, 004225523741,
    000434322335, 017270762570, 001110745622, 016754305067,
    003665275103, 014021635746, 002341612414, 015505252251,
    030123772745, 027767332100, 031407315252, 026243755417,
    033372625573, 024536265336, 032656242064, 025012602621
    },
    { 000000000000, 027052442735, 020110663677, 007142221142,
    036314221173, 011346663646, 016204442704, 031256000031,
    034630642366, 013662200453, 014720021511, 033772463224,
    002524463215, 025576021520, 022434200462, 005466642357,
    007554262351, 020506620464, 027444401526, 000416043213,
    031640043222, 016612401517, 011750620455, 036702262360,
    033364420037, 014336062702, 013274243640, 034226601175,
    005070601144, 022022243671, 025160062733, 002132420006,
    021305022727, 006357460012, 001215641150, 026247203665,
    017011203654, 030043641161, 037101460023, 010153022716,
    015535660441, 032567222374, 035425003236, 012477441503,
    023621441532, 004673003207, 003731222345, 024763660470,
    026651240476, 001603602343, 006741423201, 021713061534,
    010545061505, 037517423230, 030455602372, 017407240447,
    012061402710, 035033040025, 032171261167, 015123623652,
    024375623663, 003327261156, 004265040014, 023237402721,
    034727723253, 013775361566, 014637140424, 033665502311,
    002433502320, 025461140415, 022523361557, 005571723262,
    000117161135, 027145523600, 020007702742, 007055340077,
    036203340046, 011251702773, 016313523631, 031341161104,
    033273541102, 014221103637, 013363322775, 034331760040,
    005167760071, 022135322744, 025077103606, 002025541133,
    007443303264, 020411741551, 027553560413, 000501122326,
    031757122317, 016705560422, 011647741560, 036615303255,
    015422701574, 032470343241, 035532162303, 012560520436,
    023736520407, 004764162332, 003626343270, 024674701545,
    021212143612, 006240501127, 001302720065, 026350362750,
    017106362761, 030154720054, 037016501116, 010044143623,
    012176563625, 035124121110, 032066300052, 015034742767,
    024262742756, 003230300063, 004372121121, 023320563614,
    026746321543, 001714763276, 006656542334, 021604100401,
    010452100430, 037400542305, 030542763247, 017510321572,
    007762320122, 020730762617, 027672543755, 000620101060,
    031476101051, 016424543764, 011566762626, 036534320113,
    033152562244, 014100120571, 013042301433, 034010743306,
    005246743337, 022214301402, 025356120540, 002304562275,
    000236142273, 027264500546, 020326721404, 007374363331,
    036122363300, 011170721435, 016032500577, 031060142242,
    034406700115, 013454342620, 014516163762, 033544521057,
    002712521066, 025740163753, 022602342611, 005650700124,
    026467302605, 001435740130, 006577561072, 021525123747,
    010773123776, 037721561043, 030663740101, 017631302634,
    012257540563, 035205102256, 032347323314, 015315761421,
    024143761410, 003111323325, 004053102267, 023001540552,
    021133160554, 006161522261, 001023703323, 026071341416,
    017227341427, 030275703312, 037337522250, 010365160565,
    015703722632, 032751360107, 035613141045, 012641503770,
    023417503741, 004445141074, 003507360136, 024555722603,
    033045403371, 014017041444, 013155260506, 034107622233,
    005351622202, 022303260537, 025241041475, 002213403340,
    007675241017, 020627603722, 027765422660, 000737060155,
    031561060164, 016533422651, 011471603713, 036423241026,
    034511661020, 013543223715, 014401002657, 033453440162,
    002605440153, 025657002666, 022715223724, 005747661011,
    000321023346, 027373461473, 020231640531, 007263202204,
    036035202235, 011067640500, 016125461442, 031177023377,
    012340421456, 035312063363, 032250242221, 015202600514,
    024054600525, 003006242210, 004144063352, 023116421467,
    026570263730, 001522621005, 006460400147, 021432042672,
    010664042643, 037636400176, 030774621034, 017726263701,
    015614643707, 032646201032, 035704020170, 012756462645,
    023500462674, 004552020141, 003410201003, 024442643736,
    021024001461, 006076443354, 001134662216, 026166220523,
    017330220512, 030362662227, 037220443365, 010272001450
    },
    { 000000000000, 025433610470, 013067621160, 036454031510,
    026057442740, 003464252330, 035030263620, 010403473250,
    022102663705, 007531073375, 031165042665, 014556652215,
    004155221045, 021566431435, 017132400125, 032501210555,
    032330221217, 017703431667, 021357400377, 004764210707,
    014367663557, 031754073127, 007300042437, 022733652047,
    010232442512, 035601252162, 003255263472, 026666473002,
    036265000252, 013656610622, 025202621332, 000631031742,
    012755324033, 037366534443, 001732505153, 024301315523,
    034702766773, 011331176303, 027765147613, 002356757263,
    030657547736, 015264357346, 023630366656, 006203576226,
    016600105076, 033233715406, 005667724116, 020254134566,
    020465105224, 005056715654, 033402724344, 016031134734,
    006432547564, 023001357114, 015455366404, 030066576074,
    002567766521, 027154176151, 011500147441, 034133757031,
    024530324261, 001103534611, 037557505301, 012164315771,
    025632450467, 000201240017, 036655271507, 013266461177,
    003665012327, 026256602757, 010602633247, 035231023637,
    007730233362, 022303423712, 014757412202, 031364202672,
    021767671422, 004354061052, 032700050542, 017333640132,
    017502671670, 032131061200, 004565050710, 021156640360,
    031555233130, 014166423540, 022532412050, 007101202420,
    035400012175, 010033602505, 026467633015, 003054023465,
    013457450635, 036064240245, 000430271755, 025003461325,
    037167774454, 012554164024, 024100155534, 001533745144,
    011130336314, 034503526764, 002157517274, 027564307604,
    015065117351, 030456707721, 006002736231, 023431126641,
    033032555411, 016401345061, 020055374571, 005466564101,
    005257555643, 020664345233, 016230374723, 033603564353,
    023200117103, 006633707573, 030267736063, 015654126413,
    027355336146, 002766526536, 034332517026, 011701307456,
    001302774606, 024731164276, 012365155766, 037756745316,
    013465321156, 036056531526, 000402500036, 025031310446,
    035432763616, 010001173266, 026455142776, 003066752306,
    031567542653, 014154352223, 022500363733, 007133573343,
    017530100113, 032103710563, 004557721073, 021164131403,
    021755100341, 004366710731, 032732721221, 017301131651,
    007702542401, 022331352071, 014765363561, 031356573111,
    003657763444, 026264173034, 010630142524, 035203752154,
    025600321304, 000233531774, 036667500264, 013254310614,
    001330005165, 024703615515, 012357624005, 037764034475,
    027367447625, 002754257255, 034300266745, 011733476335,
    023232666660, 006601076210, 030255047700, 015666657370,
    005265224120, 020656434550, 016202405040, 033631215430,
    033000224372, 016433434702, 020067405212, 005454215662,
    015057666432, 030464076042, 006030047552, 023403657122,
    011102447477, 034531257007, 002165266517, 027556476167,
    037155005337, 012566615747, 024132624257, 001501034627,
    036257771531, 013664161141, 025230150451, 000603740021,
    010200333271, 035633523601, 003267512311, 026654302761,
    014355112234, 031766702644, 007332733354, 022701123724,
    032302550574, 017731340104, 021365371414, 004756561064,
    004167550726, 021554340356, 017100371646, 032533561236,
    022130112066, 007503702416, 031157733106, 014564123576,
    026065333023, 003456523453, 035002512143, 010431302533,
    000032771763, 025401161313, 013055150603, 036466740273,
    024502455502, 001131245172, 037565274462, 012156464012,
    002555017242, 027166607632, 011532636322, 034101026752,
    006400236207, 023033426677, 015467417367, 030054207717,
    020457674547, 005064064137, 033430055427, 016003645057,
    016632674715, 033201064365, 005655055675, 020266645205,
    030665236055, 015256426425, 023602417135, 006231207545,
    034730017010, 011303607460, 027757636170, 002364026500,
    012767455750, 037354245320, 001700274630, 024333464240
    },
    { 000000000000, 003132630357, 030350106333, 033262736064,
    016715772662, 015627142535, 026445674551, 025577044606,
    003706003140, 000634633217, 033456105273, 030564735124,
    015013771722, 016121141475, 025343677411, 026271047746,
    007614006300, 004726636057, 037544100033, 034476730364,
    011101774562, 012033144635, 021251672651, 022363042506,
    004112005240, 007020635117, 034242103173, 037370733224,
    012607777422, 011735147775, 022557671711, 021465041446,
    021505572205, 022437342152, 011655474136, 012767244261,
    037210200467, 034322430730, 007140306754, 004072536403,
    022203571345, 021331341012, 012153477076, 011061247321,
    034516203527, 037424433670, 004646305614, 007774535543,
    026311574105, 025223344252, 016041472236, 015173242161,
    030404206767, 033536436430, 000754300454, 003666530703,
    025417577045, 026525347312, 015747471376, 016675241021,
    033302205627, 030230435570, 003052303514, 000160533643,
    035326602016, 036214032341, 005076704325, 006144134072,
    023433170674, 020501740523, 013763076547, 010651646610,
    036420601156, 035512031201, 006770707265, 005642137132,
    020335173734, 023207743463, 010065075407, 013157645750,
    032532604316, 031400034041, 002662702025, 001750132372,
    024227176574, 027315746623, 014177070647, 017045640510,
    031234607256, 032306037101, 001164701165, 002056131232,
    027521175434, 024413745763, 017671073707, 014743643450,
    014623370213, 017711540144, 024573276120, 027441446277,
    002136402471, 001004232726, 032266504742, 031354334415,
    017125373353, 014017543004, 027275275060, 024347445337,
    001630401531, 002702231666, 031560507602, 032452337555,
    013037376113, 010105546244, 023367270220, 020255440177,
    005722404771, 006610234426, 035472502442, 036540332715,
    010731375053, 013603545304, 020461273360, 023553443037,
    006024407631, 005116237566, 036374501502, 035246331655,
    032655604034, 031767034363, 002505702307, 001437132050,
    024140176656, 027072746501, 014210070565, 017322640632,
    031153607174, 032061037223, 001203701247, 002331131110,
    027646175716, 024774745441, 017516073425, 014424643772,
    035041602334, 036173032063, 005311704007, 006223134350,
    023754170556, 020666740601, 013404076665, 010536646532,
    036747601274, 035675031123, 006417707147, 005525137210,
    020052173416, 023160743741, 010302075725, 013230645472,
    013350376231, 010262546166, 023000270102, 020132440255,
    005445404453, 006577234704, 035715502760, 036627332437,
    010456375371, 013564545026, 020706273042, 023634443315,
    006343407513, 005271237644, 036013501620, 035121331577,
    014544370131, 017476540266, 024614276202, 027726446155,
    002251402753, 001363232404, 032101504460, 031033334737,
    017242373071, 014370543326, 027112275342, 024020445015,
    001557401613, 002465231544, 031607507520, 032735337677,
    007573006022, 004441636375, 037623100311, 034711730046,
    011266774640, 012354144517, 021136672573, 022004042624,
    004275005162, 007347635235, 034125103251, 037017733106,
    012560777700, 011452147457, 022630671433, 021702041764,
    000367000322, 003255630075, 030037106011, 033105736346,
    016472772540, 015540142617, 026722674673, 025610044524,
    003461003262, 000553633135, 033731105151, 030603735206,
    015374771400, 016246141757, 025024677733, 026116047464,
    026076574227, 025144344170, 016326472114, 015214242243,
    030763206445, 033651436712, 000433300776, 003501530421,
    025770577367, 026642347030, 015420471054, 016512241303,
    033065205505, 030157435652, 003335303636, 000207533561,
    021662572127, 022750342270, 011532474214, 012400244143,
    037177200745, 034045430412, 007227306476, 004315536721,
    022164571067, 021056341330, 012234477354, 011306247003,
    034671203605, 037743433552, 004521305536, 007413535661
    },
    { 000000000000, 031013001550, 022026203320, 013035202670,
    032161360245, 003172361715, 010147163165, 021154162435,
    012377226516, 023364227046, 030351025636, 001342024366,
    020216146753, 011205147203, 002230345473, 033223344123,
    024676455634, 015665454364, 006650656514, 037643657044,
    016717735471, 027704734121, 034731536751, 005722537201,
    036501673322, 007512672672, 014527470002, 025534471552,
    004460513167, 035473512437, 026446710247, 017455711717,
    027540655475, 016553654125, 005566456755, 034575457205,
    015421535630, 024432534360, 037407736510, 006414737040,
    035637473163, 004624472433, 017611670243, 026602671713,
    007756713326, 036745712676, 025770510006, 014763511556,
    003336200241, 032325201711, 021310003161, 010303002431,
    031257160004, 000244161554, 013271363324, 022262362674,
    011041026757, 020052027207, 033067225477, 002074224127,
    023120346512, 012133347042, 001106145632, 030115144362,
    017201733572, 026212732022, 035227530652, 004234531302,
    025360453737, 014373452267, 007346650417, 036355651147,
    005176515064, 034165514534, 027150716344, 016143717614,
    037017675221, 006004674771, 015031476101, 024022477451,
    033477366346, 002464367616, 011451165066, 020442164536,
    001516006103, 030505007453, 023530205223, 012523204773,
    021700140650, 010713141300, 003726343570, 032735342020,
    013661220415, 022672221145, 031647023735, 000654022265,
    030741166107, 001752167457, 012767365227, 023774364777,
    002620206342, 033633207612, 020606005062, 011615004532,
    022436340411, 013425341141, 000410143731, 031403142261,
    010557020654, 021544021304, 032571223574, 003562222024,
    014137533733, 025124532263, 036111730413, 007102731143,
    026056653576, 017045652026, 004070450656, 035063451306,
    006240715225, 037253714775, 024266516105, 015275517455,
    034321475060, 005332474530, 016307676340, 027314677610,
    036403467365, 007410466635, 014425664045, 025436665515,
    004562707120, 035571706470, 026544504200, 017557505750,
    024774641673, 015767640323, 006752442553, 037741443003,
    016615521436, 027606520166, 034633722716, 005620723246,
    012275032551, 023266033001, 030253231671, 001240230321,
    020314352714, 011307353244, 002332151434, 033321150164,
    000102214047, 031111215517, 022124017367, 013137016637,
    032063174202, 003070175752, 010045377122, 021056376472,
    011143232710, 020150233240, 033165031430, 002176030160,
    023022152555, 012031153005, 001004351675, 030017350325,
    003234014206, 032227015756, 021212217126, 010201216476,
    031355374043, 000346375513, 013373177363, 022360176633,
    035735667124, 004726666474, 017713464204, 026700465754,
    007654507361, 036647506631, 025672704041, 014661705511,
    027442441432, 016451440162, 005464642712, 034477643242,
    015523721677, 024530720327, 037505522557, 006516523007,
    021602354617, 010611355347, 003624157537, 032637156067,
    013763034452, 022770035102, 031745237772, 000756236222,
    033575172301, 002566173651, 011553371021, 020540370571,
    001414212144, 030407213414, 023432011264, 012421010734,
    005074701023, 034067700573, 027052502303, 016041503653,
    037115461266, 006106460736, 015133662146, 024120663416,
    017303527535, 026310526065, 035325724615, 004336725345,
    025262647770, 014271646220, 007244444450, 036257445100,
    006342501262, 037351500732, 024364702142, 015377703412,
    034223661027, 005230660577, 016205462307, 027216463657,
    014035727774, 025026726224, 036013524454, 007000525104,
    026154447531, 017147446061, 004172644611, 035161645341,
    022534154456, 013527155106, 000512357776, 031501356226,
    010455234613, 021446235343, 032473037533, 003460036063,
    030643372140, 001650373410, 012665171260, 023676170730,
    002722012305, 033731013655, 020704211025, 011717210575
    },
    { 000000000000, 004737236111, 011676474222, 015141642333,
    015540416441, 011277620550, 004336062663, 000401254772,
    033201035502, 037536203413, 022477441720, 026340677631,
    026741423143, 022076615052, 037137057361, 033600261270,
    026402273204, 022335045315, 037274607026, 033543431137,
    033142665645, 037675453754, 022734211467, 026003027576,
    015603246706, 011134070617, 004075632524, 000742404435,
    000343650347, 004474466256, 011535224165, 015202012074,
    023131200015, 027606036104, 032747674237, 036070442326,
    036471616454, 032346420545, 027207262676, 023530054767,
    010330235517, 014407003406, 001546641735, 005271477624,
    005670623156, 001147415047, 014006257374, 010731061265,
    005533073211, 001204245300, 014345407033, 010472631122,
    010073465650, 014744653741, 001605011472, 005132227563,
    036732046713, 032005270602, 027144432531, 023673604420,
    023272450352, 027545666243, 032404024170, 036333212061,
    006262600032, 002555436123, 017414274210, 013323042301,
    013722216473, 017015020562, 002154662651, 006663454740,
    035063635530, 031754403421, 024615241712, 020122077603,
    020523223171, 024214015060, 031355657353, 035462461242,
    020660473236, 024157645327, 031016007014, 035721231105,
    035320065677, 031417253766, 024556411455, 020261627544,
    013461446734, 017356670625, 002217032516, 006520204407,
    006121050375, 002616266264, 017757424157, 013060612046,
    025353400027, 021464636136, 034525074205, 030212242314,
    030613016466, 034124220577, 021065462644, 025752654755,
    016152435525, 012665603434, 007724041707, 003013277616,
    003412023164, 007325215075, 012264457346, 016553661257,
    003751673223, 007066445332, 012127207001, 016610031110,
    016211265662, 012526053773, 007467611440, 003350427551,
    030550646721, 034267470630, 021326232503, 025411004412,
    025010250360, 021727066271, 034666624142, 030151412053,
    014445400464, 010372636575, 005233074646, 001504242757,
    001105016025, 005632220134, 010773462207, 014044654316,
    027644435166, 023173603077, 036032041344, 032705277255,
    032304023527, 036433215436, 023572457705, 027245661614,
    032047673660, 036770445771, 023631207442, 027106031553,
    027507265221, 023230053330, 036371611003, 032446427112,
    001246646362, 005571470273, 010430232140, 014307004051,
    014706250723, 010031066632, 005170624501, 001647412410,
    037574600471, 033243436560, 026302274653, 022435042742,
    022034216030, 026703020121, 033642662212, 037175454303,
    004775635173, 000042403062, 015103241351, 011634077240,
    011235223532, 015502015423, 000443657710, 004374461601,
    011176473675, 015641645764, 000700007457, 004037231546,
    004436065234, 000301253325, 015240411016, 011577627107,
    022377446377, 026440670266, 033501032155, 037236204044,
    037637050736, 033100266627, 026041424514, 022776612405,
    012627200456, 016110036547, 003051674674, 007766442765,
    007367616017, 003450420106, 016511262235, 012226054324,
    021426235154, 025311003045, 030250641376, 034567477267,
    034166623515, 030651415404, 025710257737, 021027061626,
    034225073652, 030512245743, 025453407470, 021364631561,
    021765465213, 025052653302, 030113011031, 034624227120,
    007024046350, 003713270241, 016652432172, 012165604063,
    012564450711, 016253666600, 003312024533, 007425212422,
    031716000443, 035021236552, 020160474661, 024657642770,
    024256416002, 020561620113, 035420062220, 031317254331,
    002517035141, 006220203050, 013361441363, 017456677272,
    017057423500, 013760615411, 006621057722, 002116261633,
    017314273647, 013423045756, 006562607465, 002255431574,
    002654665206, 006163453317, 013022211024, 017715027135,
    024115246345, 020622070254, 035763632167, 031054404076,
    031455650704, 035362466615, 020223224526, 024514012437
    }
};
